/**
 * @Description: jira提问器
 * @author Beon
 * @date 2021/1/14
*/
import * as inquirer from 'inquirer';
import {OraLoading} from '../decorators/oraLoading';
import {ErrorCatch} from '../decorators/errorCatch';
import {Jira} from '../api/jira';
import {LzgitCliFile, lzgitJson} from '../utils/lzgitCliFile';
import {DealObj, JiraList, JiraObj} from '../types/jiraData';

export type backJiraData = string|string[]

export class JiraInquirer {
    @OraLoading.beProxy
    static status: OraLoading;
    private static username: string;
    private static password: string;
    private static inquirerObj
    private static choosenJira: backJiraData;
    private static chooseList = {
        type: 'list',
        name: 'jira',
        message: '选择您的jira号',
        choices: []
    }
    private static inputJira = {
        type: 'input',
        name: 'jira',
        message: '输入您的任务信息',
    }
    private static inputUser = [
        {
            type: 'input',
            name: 'username',
            message: '请输入您的账号'
        },
        {
            type: 'password',
            name: 'password',
            message: '请输入您的密码'
        }
    ]
    private static isReWrite = {
        type: 'confirm',
        name: 'check',
        message: '是否重新输入信息'
    }

    /**
     * 执行jira提问器
     * @returns {Promise<void>}
     */
    static async jiraInquirer(): Promise<backJiraData> {
        await this.jiraGet();

        this.status.oraLoadingStop();

        while (!this.choosenJira){
            this.dealInquirerStep();

            const INQUIRERDATA: { jira: backJiraData } = await inquirer
                .prompt(this.inquirerObj);

            if (INQUIRERDATA.jira[0] === 'byManual') {
                delete this.chooseList.choices;
                continue;
            }

            this.choosenJira = INQUIRERDATA.jira;
        }

        this.status.oraLoadingStart();

        return this.choosenJira;
    }

    /**
     * 巧妙处理提问题数据
     */
    private static dealInquirerStep(): void {
        this.inquirerObj = this.chooseList.choices ? this.chooseList : this.inputJira;
    }

    /**
     * 获取jira主方法
     * @returns {Promise<DealObj[]>}
     */
    private static async jiraGet(): Promise<void> {
        if (!await this.checkPassword()) {
            this.status.oraLoadingStop();

            await this.inputPassword();

            this.status.oraLoadingStart();
        }

        this.chooseList.choices = await this.listDeal(await this.listGet());
    }

    /**
     * 处理参数
     * @param {*} response 返回参数
     * @returns {{name: string, value: string[]}[]}
     */
    @ErrorCatch.errorExit('参数处理出错，可能是jira版本不一致')
    private static listDeal(response: JiraList): DealObj[] {
        if (response && response.issueTable.table.length) {
            const backList = response.issueTable.table.map((item: JiraObj) => ({
                name: `${item.key} ${item.summary}`,
                value: [item.key, item.summary]
            }));
            backList.unshift({
                name: '手动输入',
                value: ['byManual']
            });
            return backList;
        }

        console.log('您当前没有jira，请手动填写提交信息'.warning);
    }

    /**
     * jira列表获取
     * @returns {Promise<JiraList>}
     */
    private static async listGet(): Promise<JiraList> {
        try {
            return await Jira.jiraList({
                layoutKey: 'split-view',
                jql: 'assignee = currentUser() AND resolution = Unresolved order by updated DESC',
                // eslint-disable-next-line camelcase
                os_username: this.username,
                // eslint-disable-next-line camelcase
                os_password: this.password
            });
        } catch (e) {
            console.log('\n请求jira列表失败'.debug);
            console.log(`\n${e.stack}`.debug);
            await this.removePassword();
            process.exit(1);
        }
    }

    /**
     * 删除错误账号密码
     * @returns {Promise<void>}
     */
    private static async removePassword(): Promise<void> {
        this.status.oraLoadingStop();

        const getMessage = await inquirer
            .prompt([this.isReWrite]);

        if (getMessage.check) {
            await LzgitCliFile.wirteFile({
                username: '',
                password: '',
                jira: ''
            });
        }

        this.status.oraLoadingStart();
    }

    /**
     * 检查账号密码是否存在
     * @returns {Promise<boolean>}
     */
    private static async checkPassword(): Promise<boolean> {
        try {
            const json = await LzgitCliFile.getFileData(['username', 'password']) as lzgitJson;

            if (!json || !json.username || !json.password){
                return false;
            }

            [this.username, this.password] = [json.username, json.password];
            return true;
        } catch (e) {
            return false;
        }
    }

    /**
     * 输入账号密码
     * @returns {Promise<void>}
     */
    private static async inputPassword(): Promise<void> {
        const getMessage = await inquirer
            .prompt(this.inputUser);

        [this.username, this.password] = [getMessage.username, getMessage.password];

        await LzgitCliFile.wirteFile({
            username: getMessage.username,
            password: getMessage.password
        });
    }
}
